from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout
from django.http import HttpResponse, JsonResponse
from .forms import LoginForm, UpdateProfileForm, UpdateEmailForm,\
    AddCategoryForm,AddTagForm,AddArticleForm, UpdateArticleForm,\
    DeleteArticleForm,TopArticleForm,CategoryForm,EditCategoryForm
from django.shortcuts import render, redirect, reverse
from django.contrib.auth.decorators import login_required
from cmsauth.models import CmsUser
from qiniu import Auth, put_file
import qiniu.config
from django.views.decorators.http import require_http_methods
import hashlib
from django.core import mail

import time
from django.core.cache import cache
from article.models import ArticleModel,CategoryModel,TagModel,TopModel
from utils import mbjson
from django.forms import model_to_dict
from django.db.models import Count







#登陆  这里需要一个表单验证  需到forms文件里面编写
#登陆函数
def cms_login(request):
    if request.method == "GET":
        return render(request, 'cms_login.html')
    else:
        print (request.POST,'-'*10)
        form = LoginForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data.get('username', None)
            password = form.cleaned_data.get('password', None)
            remember = form.cleaned_data.get('remember',None)

            #先用authenticate进行验证

            user = authenticate(username=username,password=password)

            if user: #如果用户名正确，返回index页面

                login(request, user)
                if remember:
                    request.session.set_expiry(None)
                else:
                    request.session.set_expiry(0)
                nexturl = request.GET.get('next')
                if nexturl:

                    return redirect(nexturl)
                else:
                    return redirect(reverse('cms_article_manage'))
            else:
                return render(request, 'cms_login.html', context={'error': u'用户名或密码错误!'})
        else:
            return render(request,'cms_login.html',{'error':form.get_error()})

#登出函数
def cms_logout(request):
    logout(request)
    return redirect(reverse('cms_login'))



def nihao(request):
    return HttpResponse(u'你好')


def settings(request):
    return render(request, 'settings.html')

@login_required
@require_http_methods(['POST'])
def update_profile(request):
	# """
	# 	更新用户信息
	# 	1. 更新头像(avatar)
	# 	2. 更新用户名(username)
	# """
	form = UpdateProfileForm(request.POST)
	if form.is_valid():

		avatar = form.cleaned_data.get('avatar',None)
		username = form.cleaned_data.get('username',None)
		# user = request.user
		user = User.objects.all().first() # 中间件设置当前的user到request上
		user.username = username
		user.save()
		# 1.如果CmsUser这个表里已经有数据和user对应了,就直接更新
		cmsuser = CmsUser.objects.filter(user__pk=user.pk).first()
		if not cmsuser:
			# 2.如果CmsUser这个表里没有数据和user对应,就应该新建,然后保存进去
			cmsuser = CmsUser(avatar=avatar,user=user)
		else:
			cmsuser.avatar = avatar
		cmsuser.save()
		return mbjson.json_result()
	else:
		return form.get_error_response()


#@login_required
@require_http_methods(['GET'])
def get_token(request):
    #1.先要设置access_key和SeretKey
    access_key = 'qld9uXZLcLB6uQ-IaV2F4GKf0HFQo-aoVk2AKvQI'
    secret_key = 'azrEGkgF5ATgOwLADH1rwTxrE6f2c1rzYkY9jum8'
    #2.授权
    q = Auth(access_key,secret_key)
    #3.设置七牛空间
    bucket_name = 'mbspace'
    #4.生成token
    token = q.upload_token(bucket_name)
    #5.返回token
    return mbjson.json_result(kwargs={'uptoken':token})


#以下是邮箱设置函数

@login_required
@require_http_methods(['GET'])
def email_success(request):
    return render(request,'cms_emailsuccess.html')

@login_required
@require_http_methods(['GET'])
def email_fail(request):
    return render(request,'cms_emailfail.html')



@login_required
@require_http_methods(['GET','POST'])
def update_email(request):
    if request.method == 'GET':
        return render(request, 'cms_email.html')
    else:
        form = UpdateEmailForm(request.POST)
        if form.is_valid():
            email = form.cleaned_data.get('email',None)
            if email:
                #发送链接到Email这个邮箱
                #1. 把用户的邮箱信息存储到缓存中
                code = hashlib.md5(str(time.time().encode(encoding='utf-8'))+email).hexdigest()
                cache.set(code,email,120)
                #2.发送右脚到Email这个邮箱
                check_url = request.scheme + ' ://' +request.get_host()+reverse('cms_check_email',kwargs={'code':code})
                subject=u'邮箱修改验证'
                #message中应该包含验证的链接
                message = u'博客验证链接，点击'+check_url + u' ,请在10分钟以内完成注册。工作人员不会向您索取验证码，请勿泄露。消息来自：明明的博客'
                from_mail = '1903476826@qq.com'
                recipient_list = [email]
                mail.send_mail(subject,message,from_mail,recipient_list)
                return HttpResponse('success')
        else:
            return render(request,'cms_email.html',{'error':form.errors})


@login_required  #需要登陆
@require_http_methods(['GET']) #设定方法
def check_email(request,code):
    if len(code)>0:
        email = cache.get(code)
        print(email)
        if email:
            user = request.user
            user.email = email
            user.save(update_fields=['email'])
            return HttpResponse(u'邮箱修改成功')
        else:
            return HttpResponse(u'该连接已经失效')
    else:
        return HttpResponse(u'该连接已经失效')

#文章相关操作
@login_required
def article_manage(request,page=1,category_id=0):
    #获取所有的文章
    NUM_PAGE = 5   #定义每一页展示5篇文章
    categoryId = int(category_id)
    currentPage = int(page)
    numPage = int(NUM_PAGE)
    articles = None
    if categoryId > 0:

        articles=ArticleModel.objects.all().filter(category__pk = categoryId).order_by('-release_time')
    else:
        articles = ArticleModel.objects.all().order_by('-top__operate_time','-release_time')
    start = (currentPage-1)*numPage
    end = start + numPage
    #算出文章总数
    articleCount = articles.count()
    #对文章进行切片
    articles = articles[start:end]
    #总共有多少页
    pageCount = articleCount/numPage
    if articleCount % numPage > 0:
        pageCount += 1
    pages = []   #用来装当前页面的所有分页序号
    #先往前找
    tmpPage = currentPage - 1   #定义一个临时参数等于当前页面  满足最大的条件，tmpPage不能小于1
    while tmpPage >= 1:
        if tmpPage % 5 == 0:
            break
        else:
            pages.append(tmpPage)
            tmpPage -= 1
    #往后找
    tmpPage = currentPage
    while tmpPage <= pageCount:
        if tmpPage % 5 == 0:
            pages.append(tmpPage)
            break
        else:
            pages.append(tmpPage)
            tmpPage += 1
    pages.sort()
#获取所有的分类
    categorys = CategoryModel.objects.all()

    context={
        'c_page': currentPage,
        't_page': pageCount,
        'pages': pages,
        'articles': articles,
        'categorys': categorys,
        'c_category': categoryId
    }
    return render(request, 'cms_article_manage.html',context=context)

@login_required
def add_article(request):
    if request.method == 'GET':
        categorys = CategoryModel.objects.all()  #到article里的models里面建立categorys模型
        tags = TagModel.objects.all()
        data = {
            'categorys': categorys,
            'tags': tags
        }
        return render(request, 'cms_addarticle.html', data)
    else:
        form = AddArticleForm(request.POST)
        if form.is_valid():
            title = form.cleaned_data.get('title')
            category = form.cleaned_data.get('category')
            desc=form.cleaned_data.get('desc')
            thumbnail=form.cleaned_data.get('thumbnail')
            content_html = form.cleaned_data.get('content_html')
            tags=request.POST.getlist('tags[]')
            user=request.user
            categoryModel=CategoryModel.objects.filter(pk=category).first()
            articleModel = ArticleModel(title=title,desc=desc,thumbnail=thumbnail,content_html=content_html,author=user,category=categoryModel)
            articleModel.save()
            #添加tags的多对多
            if tags:
                for tag in tags:
                    tagModel = TagModel.objects.filter(pk=int(tag)).first()
                    if tagModel:
                        articleModel.tags.add(tagModel)
            return mbjson.json_result(data={})
        else:
            return form.get_error_response()




@login_required
@require_http_methods(['GET','POST'])
def edit_article(request, pk=''):

    if request.method =='GET':
        article= ArticleModel.objects.filter(pk=pk).first()
        articleDict = model_to_dict(article)  #model_to_dict  能够将model型变成字典形式
        articleDict['tags'] = []
        for tagModel in article.tags.all():
            articleDict['tags'].append(tagModel.id)
        context={
            'article': article,
            'categorys':CategoryModel.objects.all(),
            'tags':TagModel.objects.all()
        }
        print('----' * 20)

        return render(request, 'cms_edit_article.html', context)
    else:
        form = UpdateArticleForm(request.POST)
        if form.is_valid():
            title = form.cleaned_data.get('title')
            category = form.cleaned_data.get('category')  #分类
            desc = form.cleaned_data.get('desc')
            thumbnail = form.cleaned_data.get('thumbnail')

            print(thumbnail)
            content_html = form.cleaned_data.get('content_html')
            tags = request.POST.getlist('tags')

            uid=form.cleaned_data.get('uid')
            articleModel = ArticleModel.objects.filter(pk=uid).first()

            if articleModel:
                articleModel.title=title
                articleModel.desc=desc
                articleModel.thumbnail=thumbnail
                articleModel.content_html=content_html
                articleModel.category=CategoryModel.objects.filter(pk=category).first()
                articleModel.save()

                if tags:
                    for tag in tags:
                        tagModel=TagModel.objects.filter(pk=tag).first()
                        articleModel.tags.add(tagModel)
                    return mbjson.json_result()
            else:
                return mbjson.json_params_error(message=form.errors.as_json())


@login_required
@require_http_methods(['POST'])
def delete_article(request):
    form = DeleteArticleForm(request.POST)
    if form.is_valid():
        uid = form.cleaned_data.get('uid')
        articleModel=ArticleModel.objects.filter(pk=uid).first()
        if articleModel:
            articleModel.delete()
            return mbjson.json_result()
        else:
            return mbjson.json_params_error(message=u'该博客不存在')
    else:
        return form.get_error_response()


@login_required
@require_http_methods(['POST'])
def top_article(request):
    form = TopArticleForm(request.POST)
    if form.is_valid():
        uid = form.cleaned_data.get('uid')
        articleModel = ArticleModel.objects.filter(pk=uid).first()
        print(articleModel)
        if articleModel:
            if not articleModel.htumbnail:
                return mbjson.json_params_error(message=u'有缩略图的文章才能置顶')
            topModel = articleModel.top
            if not topModel:
                topModel = TopModel()
                topModel.save()

                articleModel.top = topModel
                articleModel.save(update_fields=['top'])
                return mbjson.json_result()
            else:
                return mbjson.json_params_error(message=u'该文章不存在')
        else:
            return form.get_error_response()


@login_required
@require_http_methods(['POST'])
def untop_article(request):
    form = TopArticleForm(request.POST)
    if form.is_valid():
        uid = form.cleaned_data.get('uid')
        articleModel = ArticleModel.objects.filter(pk=uid).first()
        if articleModel:
            if articleModel.top:
                topModel = articleModel.top
                topModel.delete()
                return mbjson.json_result()
            else:
                return mbjson.json_params_error(message=u'本文章未置顶')
        else:
            return mbjson.json_params_error(message=u'该文章不存在')

    else:
        return form.get_error_response()

#以下是所有的分类操作
@login_required
@require_http_methods(['GET'])
def category_manage(request):
    if request.method=='GET':
        #annotate 这个函数会给queryset当中的所有的模型添加属性，具体的属性根据提供的聚合函数而定
        categorys = CategoryModel.objects.all().annotate(num_articles=Count('articlemodel')).order_by('-num_articles')
        context = {
            'categorys':categorys
        }
        return render(request,'cms_category_manage.html',context)

@login_required
@require_http_methods(['POST'])
def edit_category(request):
    form = EditCategoryForm(request.POST)
    if form.is_valid():
        categoryId = form.cleaned_data.get('category_id')
        name = form.cleaned_data.get('name')
        categoryModel = CategoryModel.objects.filter(pk=categoryId).first()
        if categoryModel:
            categoryModel.name=name
            categoryModel.save(update_fields=['name'])  #如果分类存在修改name
            return mbjson.json_result()
        else:
            return mbjson.json_params_error(message=u'该分类不存在')
    else:
        return form.get_error_response()

@login_required
@require_http_methods(['POST'])
def delete_category(request):
    form = CategoryForm(request.POST)
    if form.is_valid():
        categoryId = form.cleaned_data.get('category_id')
        categoryModel = CategoryModel.objects.filter(pk=categoryId).first()
        if categoryModel:
            #首先拿到该分类下的文章数量  ，如果文章数量大于0，就不让删除
            articleCount = categoryModel.articlemodel_set.all().count()
            if articleCount > 0 :
                return mbjson.json_params_error(message=u'该分类下还存有文章，不能删除')
            else:
                categoryModel.delete()
                return mbjson.json_result()

        else:
            return mbjson.json_params_error(message=u'该分类不存在')
    else:
        return form.get_error_response()






@login_required
@require_http_methods(['POST'])
def add_category(request):
    form = AddCategoryForm(request.POST)
    if form.is_valid():
        categoryname = form.cleaned_data.get('categoryname',None)
        resultCategory = CategoryModel.objects.filter(name=categoryname).first()
        if not resultCategory:
            categoryModel=CategoryModel(name=categoryname)
            categoryModel.save()
            return mbjson.json_result(data={'id':categoryModel.id,'name': categoryModel.name})
        else:
            return mbjson.json_params_error(message=u'不能设置同名的分类！')
    else:
        return mbjson.json_params_error(message=u'表单验证失败')   #请求参数错误

#@login_required
@require_http_methods(['POST'])
def add_tag(request):
    form = AddTagForm(request.POST)
    if form.is_valid():
        tagname=form.cleaned_data.get('tagname')
        resultTag = TagModel.objects.filter(name=tagname).first()#判断数据库里面是否有同名的tagname
        if not resultTag:  #如果没有，说明可以添加
            tagModel=TagModel(name=tagname)
            tagModel.save()
            return mbjson.json_result(data={'id':tagModel.id,'name':tagModel.name})
        else:
            return mbjson.json_params_error(message=u'不能设置同名标签！')
    else:
        return form.get_error_response()

